package net.entelijan.cobean.examples.showcase.config.table;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import net.entelijan.cobean.data.literature.LitBook;
import net.entelijan.cobean.examples.showcase.ShowcaseTestFrame;
import net.entelijan.cobean.examples.util.ExamplesUtil;
import net.entelijan.testutil.CobeanTestUtil;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.fest.swing.fixture.FrameFixture;
import org.fest.swing.fixture.JTableFixture;
import org.fest.swing.fixture.JTextComponentFixture;
import org.junit.Test;

public class TableFestTestCase {

	private static Log log = LogFactory.getLog(TableFestTestCase.class);

	public void testPattern() {
		ConfigTablePanel panel = new ConfigTablePanel();
		CobeanTestUtil.setComponentNamesFromPropertyNames(panel);
		ShowcaseTestFrame frame = new ShowcaseTestFrame(panel);
		FrameFixture frameFix = new FrameFixture(frame);
		try {
			frameFix.show();
			pause(1000);
			ConfigTableShowcase sc = new ConfigTableShowcase();
			sc.setService(ExamplesUtil.createTestService());
			sc.init(panel);
			pause(2000);
			// final JTableFixture tableFix = frameFix.table("table");
			// final JTextComponentFixture filterTextBox =
			// frameFix.textBox("filterText");
		} finally {
			frameFix.cleanUp();
		}

	}

	@Test
	public void testSelectFromGUI() {
		ConfigTablePanel panel = new ConfigTablePanel();
		CobeanTestUtil.setComponentNamesFromPropertyNames(panel);
		ShowcaseTestFrame frame = new ShowcaseTestFrame(panel);
		FrameFixture frameFix = new FrameFixture(frame);
		try {
			frameFix.show();
			ConfigTableShowcase sc = new ConfigTableShowcase();
			sc.setService(ExamplesUtil.createTestService());
			sc.init(panel);
			final SingleSelectionModel model = sc.getModel();
			final JTableFixture tableFix = frameFix.table("booksTable");

			// Select one book
			{
				tableFix.selectCell(tableFix.cell("Miguel Street"));
				assertEquals("Miguel Street", model.getBooksSelectedValue()
						.getTitle());
			}

			// Select another book
			{
				tableFix.selectCell(tableFix.cell("The Scream"));
				assertEquals("The Scream", model.getBooksSelectedValue()
						.getTitle());
				assertEquals(2008, model.getBooksSelectedValue().getYear()
						.intValue());
			}

		} finally {
			frameFix.cleanUp();
		}

	}

	@Test
	public void testSelectFromGUIAfterSort() {
		ConfigTablePanel panel = new ConfigTablePanel();
		CobeanTestUtil.setComponentNamesFromPropertyNames(panel);
		ShowcaseTestFrame frame = new ShowcaseTestFrame(panel);
		FrameFixture frameFix = new FrameFixture(frame);
		try {
			frameFix.show();
			ConfigTableShowcase sc = new ConfigTableShowcase();
			sc.setService(ExamplesUtil.createTestService());
			sc.init(panel);
			final SingleSelectionModel model = sc.getModel();
			final JTableFixture tableFix = frameFix.table("booksTable");

			// Select a book
			{
				model.setBooksSelectedValue(model.getBooks().get(3));
				final String selectionValue = tableFix.selectionValue();
				assertEquals("A Bend in the River", selectionValue);
			}
			// Select one book
			{
				tableFix.selectCell(tableFix.cell("Miguel Street"));
				assertEquals("Miguel Street", model.getBooksSelectedValue()
						.getTitle());
			}

			// Select another book
			{
				tableFix.selectCell(tableFix.cell("The Scream"));
				assertEquals("The Scream", model.getBooksSelectedValue()
						.getTitle());
				assertEquals(2008, model.getBooksSelectedValue().getYear()
						.intValue());
			}

		} finally {
			frameFix.cleanUp();
		}

	}

	@Test
	public void testSelectAfterFilter() {
		ConfigTablePanel panel = new ConfigTablePanel();
		CobeanTestUtil.setComponentNamesFromPropertyNames(panel);
		ShowcaseTestFrame frame = new ShowcaseTestFrame(panel);
		FrameFixture frameFix = new FrameFixture(frame);
		try {
			frameFix.show();
			ConfigTableShowcase sc = new ConfigTableShowcase();
			sc.setService(ExamplesUtil.createTestService());
			sc.init(panel);
			final SingleSelectionModel model = sc.getModel();
			final JTableFixture tableFix = frameFix.table("booksTable");
			JTextComponentFixture filterTextBox = frameFix
					.textBox("booksFilterInputText");
			// Filter
			{
				filterTextBox.enterText("The");
				pause(200);
			}

			// Select a book that is not filtered
			{
				model.setBooksSelectedValue(model.getBooks().get(3));
				final String selectionValue = tableFix.selectionValue();
				assertNull(selectionValue);
			}

			// Select a cell
			{
				tableFix.selectCell(tableFix.cell("The Scream"));
				assertEquals("The Scream", model.getBooksSelectedValue()
						.getTitle());
				assertEquals(2008, model.getBooksSelectedValue().getYear()
						.intValue());
			}

			// Clear the filter
			{
				filterTextBox.deleteText();
				pause(200);
			}
			// Select a book that is not filtered
			{
				model.setBooksSelectedValue(model.getBooks().get(3));
				final String selectionValue = tableFix.selectionValue();
				assertEquals("A Bend in the River", model
						.getBooksSelectedValue().getTitle());
				assertEquals("A Bend in the River", selectionValue);
			}
			// Select a cell
			{
				tableFix.selectCell(tableFix.cell("The Scream"));
				assertEquals("The Scream", model.getBooksSelectedValue()
						.getTitle());
				assertEquals(2008, model.getBooksSelectedValue().getYear()
						.intValue());
			}
		} finally {
			frameFix.cleanUp();
		}

	}

	@Test
	public void testSelectFromModel() {
		ConfigTablePanel panel = new ConfigTablePanel();
		CobeanTestUtil.setComponentNamesFromPropertyNames(panel);
		ShowcaseTestFrame frame = new ShowcaseTestFrame(panel);
		FrameFixture frameFix = new FrameFixture(frame);
		try {
			frameFix.show();
			ConfigTableShowcase sc = new ConfigTableShowcase();
			sc.setService(ExamplesUtil.createTestService());
			sc.init(panel);
			final SingleSelectionModel model = sc.getModel();
			final JTableFixture tableFix = frameFix.table("booksTable");

			// Select a book
			{

				model.setBooksSelectedValue(model.getBooks().get(3));
				final String selectionValue = tableFix.selectionValue();
				assertEquals("A Bend in the River", selectionValue);
			}

			// Select another book
			{

				model.setBooksSelectedValue(model.getBooks().get(4));
				final String selectionValue = tableFix.selectionValue();
				assertEquals("A House for Mr Bivas", selectionValue);
			}

		} finally {
			frameFix.cleanUp();
		}

	}

	@Test
	public void testSelectFromModelAfterSort() {
		ConfigTablePanel panel = new ConfigTablePanel();
		CobeanTestUtil.setComponentNamesFromPropertyNames(panel);
		ShowcaseTestFrame frame = new ShowcaseTestFrame(panel);
		FrameFixture frameFix = new FrameFixture(frame);
		try {
			frameFix.show();
			ConfigTableShowcase sc = new ConfigTableShowcase();
			sc.setService(ExamplesUtil.createTestService());
			sc.init(panel);
			final SingleSelectionModel model = sc.getModel();
			final JTableFixture tableFix = frameFix.table("booksTable");

			log.debug("\n" + CobeanTestUtil.listToString(model.getBooks()));
			// Sort
			{
				tableFix.tableHeader().clickColumn(0);
				pause(200);
			}

			// Select a book
			{
				model.setBooksSelectedValue(model.getBooks().get(3));
				final String selectionValue = tableFix.selectionValue();
				assertEquals("A Bend in the River", selectionValue);
			}

			// Select another book
			{

				model.setBooksSelectedValue(model.getBooks().get(4));
				final String selectionValue = tableFix.selectionValue();
				assertEquals("A House for Mr Bivas", selectionValue);
			}

			// Sort the other way
			{
				tableFix.tableHeader().clickColumn(0);
				pause(200);
			}

			// Select a book
			{
				model.setBooksSelectedValue(model.getBooks().get(3));
				final String selectionValue = tableFix.selectionValue();
				assertEquals("A Bend in the River", selectionValue);
			}

			// Select another book
			{

				model.setBooksSelectedValue(model.getBooks().get(4));
				final String selectionValue = tableFix.selectionValue();
				assertEquals("A House for Mr Bivas", selectionValue);
			}
		} finally {
			frameFix.cleanUp();
		}

	}

	@Test
	public void testDelete() {
		ConfigTablePanel panel = new ConfigTablePanel();
		CobeanTestUtil.setComponentNamesFromPropertyNames(panel);
		ShowcaseTestFrame frame = new ShowcaseTestFrame(panel);
		FrameFixture frameFix = new FrameFixture(frame);
		try {
			frameFix.show();
			ConfigTableShowcase sc = new ConfigTableShowcase();
			sc.setService(ExamplesUtil.createTestService());
			sc.init(panel);
			final JTableFixture tableFix = frameFix.table("booksTable");
			assertEquals(30, tableFix.component().getModel().getRowCount());

			sc.getModel().getBooks().remove(3);
			pause(200);
			assertEquals(29, tableFix.component().getModel().getRowCount());

		} finally {
			frameFix.cleanUp();
		}

	}

	@Test
	public void testDeleteSelected() {
		ConfigTablePanel panel = new ConfigTablePanel();
		CobeanTestUtil.setComponentNamesFromPropertyNames(panel);
		ShowcaseTestFrame frame = new ShowcaseTestFrame(panel);
		FrameFixture frameFix = new FrameFixture(frame);
		try {
			frameFix.show();
			ConfigTableShowcase sc = new ConfigTableShowcase();
			sc.setService(ExamplesUtil.createTestService());
			sc.init(panel);
			final JTableFixture tableFix = frameFix.table("booksTable");
			assertEquals(30, tableFix.component().getModel().getRowCount());

			tableFix.selectCell(tableFix.cell("Ad ora incerta"));
			pause(200);
			LitBook sb = sc.getModel().getBooksSelectedValue();
			String sv = tableFix.selectionValue();
			assertEquals("Ad ora incerta", sv);

			sc.getModel().getBooks().remove(sb);
			pause(200);
			assertEquals(29, tableFix.component().getModel().getRowCount());
			tableFix.requireNoSelection();

			assertNull(sc.getModel().getBooksSelectedValue());

		} finally {
			frameFix.cleanUp();
		}

	}

	private synchronized void pause(int timeMs) {
		try {
			wait(timeMs);
		} catch (InterruptedException e) {
			// Do not mind
		}

	}

}
